﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace mstdump_Analyzer
{
    class OpenSMConf : IDisposable
    {
        private ArrayList mcgroupsList = new ArrayList(); // will save object arrays of two cells.
        private ArrayList subnetInfo = new ArrayList();
        private DataTable subnetInfoTable = null;
        private bool KEEP_RUNNING; 
        private string OUTPUT_DIR_PATH;
        //
        //----------------------------------------------------
        //
        public OpenSMConf(ref bool KEEP_RUNNING, ref string OUTPUT_DIR_PATH)
        {
            this.KEEP_RUNNING = KEEP_RUNNING;   
            this.OUTPUT_DIR_PATH = OUTPUT_DIR_PATH;

            // create a DataTable
            subnetInfoTable = new DataTable();
            // add columns
            subnetInfoTable.Columns.Add("Source  Node", typeof(string));
            subnetInfoTable.Columns.Add("Source  Port", typeof(int));
            subnetInfoTable.Columns.Add("Destination Node", typeof(string));
            subnetInfoTable.Columns.Add("Destination Port", typeof(int));
        }
        //
        //----------------------------------------------------
        //
        public ArrayList getMCGroupsList()
        {
            ArrayList res = new ArrayList();
            // add DataRows.
            for (int i = 0; i < mcgroupsList.Count; i++)
            {
                // ## MC group parameters
                MCGroupFields mcgf = (MCGroupFields)((object[])mcgroupsList[i])[0];
                string mcParameters = "MC Group: " + mcgf.mcGroup + "\r\n"
                    + "MC group parametes:\r\n"
                    + "\tmgid: " + mcgf.mgid + "\r\n"
                    + "\tport_gid: " + mcgf.port_gid + "\r\n"
                    + "\tqkey: " + mcgf.qkey + "\r\n"
                    + "\tmlid: " + mcgf.mlid + "\r\n"
                    + "\tmtu: " + mcgf.mtu + "\r\n"
                    + "\ttclass: " + mcgf.tclass + "\r\n"
                    + "\tpkey: " + mcgf.pkey + "\r\n"
                    + "\trate: " + mcgf.rate + "\r\n"
                    + "\tpkt_life: " + mcgf.pkt_life + "\r\n"
                    + "\tsl_flow_hop: " + mcgf.sl_flow_hop + "\r\n"
                    + "\tscope_state: " + mcgf.scope_state + "\r\n"
                    + "\tproxy_join: " + mcgf.proxy_join + "\r\n";
                // ## MC members
                // create a DataTable
                DataTable table = new DataTable();
                // add columns
                table.Columns.Add("port_gid", typeof(string));
                table.Columns.Add("scope_state", typeof(string));
                table.Columns.Add("proxy_join", typeof(string));
                // add DataRows.
                ArrayList membersList = (ArrayList)((object[])mcgroupsList[i])[1];
                for (int j = 0; j < membersList.Count; j++)
                {
                    MCMembersFields member = (MCMembersFields)membersList[j];
                    table.Rows.Add(member.port_gid,
                        member.scope_state,
                        member.proxy_join);
                }
                res.Add(new object[] { mcParameters, table });
            }
            return res;
        }
        //
        //----------------------------------------------------
        //
        public void scanInfo()
        {
            string path = Methods.FindFileRec(OUTPUT_DIR_PATH, "opensm-sa.dump");
            if (path != null)
            {
                scanOpensmSA(path);
            }
            path = Methods.FindFileRec(OUTPUT_DIR_PATH, "opensm-subnet.lst");
            if (path != null)
            {
                scanSubnet(path);
            }
        }
        //
        //----------------------------------------------------
        //
        private void scanOpensmSA(string srcFilePath)
        {
            if (srcFilePath == null)
                return;
            StreamReader sr = new StreamReader(srcFilePath);
            string line = "";
            bool scanningGroup = false;
            MCGroupFields mcgf = new MCGroupFields();
            ArrayList membersList = new ArrayList();
            string[] arr;
            try
            {
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    // read line
                    line = sr.ReadLine();
                    try
                    {
                        // ## get MC group parameters ##
                        if (line.Contains("MC Group"))
                        {
                            if (scanningGroup == true)
                            {
                                mcgroupsList.Add(new object[] { mcgf, membersList });
                                scanningGroup = false;
                            }
                            mcgf = new MCGroupFields();
                            membersList = new ArrayList();
                            line = Methods.RemoveExtraSpaces(line);
                            arr = Regex.Split(line, " ");
                            if (line.Contains("("))
                            {
                                mcgf.mcGroup = arr[2];
                                mcgf.mgid = Regex.Split(arr[5], @"=")[1];
                                mcgf.port_gid = Regex.Split(arr[6], @"=")[1];
                                mcgf.qkey = Regex.Split(arr[7], @"=")[1];
                                mcgf.mlid = Regex.Split(arr[8], @"=")[1];
                                mcgf.mtu = Regex.Split(arr[9], @"=")[1];
                                mcgf.tclass = Regex.Split(arr[10], @"=")[1];
                                mcgf.pkey = Regex.Split(arr[11], @"=")[1];
                                mcgf.rate = Regex.Split(arr[12], @"=")[1];
                                mcgf.pkt_life = Regex.Split(arr[13], @"=")[1];
                                mcgf.sl_flow_hop = Regex.Split(arr[14], @"=")[1];
                                mcgf.scope_state = Regex.Split(arr[15], @"=")[1];
                                mcgf.proxy_join = Regex.Split(arr[16], @"=")[1];
                            }
                            else
                            {
                                mcgf.mcGroup = arr[2];
                                mcgf.mgid = Regex.Split(arr[4], @"=")[1];
                                mcgf.port_gid = Regex.Split(arr[5], @"=")[1];
                                mcgf.qkey = Regex.Split(arr[6], @"=")[1];
                                mcgf.mlid = Regex.Split(arr[7], @"=")[1];
                                mcgf.mtu = Regex.Split(arr[8], @"=")[1];
                                mcgf.tclass = Regex.Split(arr[9], @"=")[1];
                                mcgf.pkey = Regex.Split(arr[10], @"=")[1];
                                mcgf.rate = Regex.Split(arr[11], @"=")[1];
                                mcgf.pkt_life = Regex.Split(arr[12], @"=")[1];
                                mcgf.sl_flow_hop = Regex.Split(arr[13], @"=")[1];
                                mcgf.scope_state = Regex.Split(arr[14], @"=")[1];
                                mcgf.proxy_join = Regex.Split(arr[15], @"=")[1];
                            }
                            //
                            scanningGroup = true;
                        }
                        else
                        {// ## get MC group members ##
                            if (scanningGroup && line.Contains("mcm_port"))
                            {
                                arr = Regex.Split(line, " ");
                                MCMembersFields mem = new MCMembersFields();
                                mem.port_gid = Regex.Split(arr[1], @"=")[1];
                                mem.scope_state = Regex.Split(arr[2], @"=")[1];
                                mem.proxy_join = Regex.Split(arr[3], @"=")[1];
                                membersList.Add(mem);
                            }
                        }
                    }//try
                    catch { }
                }// while
                // add the last one
                mcgroupsList.Add(new object[] { mcgf, membersList });
                // #################################################
            }//try
            catch { }
            sr.Dispose();
        }
        //
        //----------------------------------------------------
        //
        private void scanSubnet(string srcFilePath)
        {
            if (srcFilePath == null)
                return;
            StreamReader sr = new StreamReader(srcFilePath);
            string line = "";
            string[] arr;
            try
            {
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    // read line
                    line = sr.ReadLine();
                    try
                    {//Regex.Split(arr[], @":")[1];
                        arr = Regex.Split(line, " ");
                        OpensmSubnetFeilds link = new OpensmSubnetFeilds();
                        // ***********************************  Source   *********************************************
                        if (arr[1].Equals("CA"))
                        {
                            link.srcDeviceType = "HCA";
                        }
                        else
                        {
                            if(arr[1].Equals("SW"))
                            {
                                link.srcDeviceType = "Switch";
                            }
                            else
                            {
                                link.srcDeviceType = arr[1];
                            }
                        }
                        link.srcDevPortsNum = Int32.Parse(Methods.Hex2decString(Regex.Split(arr[2], @":")[1]));
                        link.srcSystemGUID = Regex.Split(arr[3], @":")[1];
                        link.srcNodeGUID = Regex.Split(arr[4], @":")[1];
                        link.srcPortGUID = Regex.Split(arr[5], @":")[1];
                        link.srcVenID = Regex.Split(arr[6], @":")[1];
                        link.srcDevID = Regex.Split(arr[7], @":")[1];
                        link.srcRev = Regex.Split(arr[8], @":")[1];

                        // srcDeviceName always begins at cell 9, find where it ends!
                        int deviceNameEnd = 10; // for hca...
                        for (int i = 9; i < arr.Length; i++)
                        {
                            link.srcDeviceName += arr[i] + " ";
                            link.srcDeviceName = Regex.Replace(link.srcDeviceName, @"{", "");
                            if (arr[i].Contains("}"))
                            {
                                link.srcDeviceName = Regex.Replace(link.srcDeviceName, @"}", "");
                                deviceNameEnd = i;
                                break;
                            }
                        }
                        link.srcLid = Int32.Parse(Methods.Hex2decString(Regex.Split(arr[deviceNameEnd + 1], @":")[1]));
                        link.srcPortNum = Int32.Parse(Methods.Hex2decString(Regex.Split(arr[deviceNameEnd + 2], @":")[1]));

                        // ***********************************  Destination   *********************************************
                        if (arr[deviceNameEnd + 5].Equals("CA"))
                        {
                            link.dstDeviceType = "HCA";
                        }
                        else
                        {
                            if (arr[deviceNameEnd + 5].Equals("SW"))
                            {
                                link.dstDeviceType = "Switch";
                            }
                            else
                            {
                                link.dstDeviceType = arr[deviceNameEnd + 5];
                            }
                        }
                        link.dstDevPortsNum = Int32.Parse(Regex.Split(arr[deviceNameEnd + 6], @":")[1]);
                        link.dstSystemGUID = Regex.Split(arr[deviceNameEnd + 7], @":")[1];
                        link.dstNodeGUID = Regex.Split(arr[deviceNameEnd + 8], @":")[1];
                        link.dstPortGUID = Regex.Split(arr[deviceNameEnd + 9], @":")[1];
                        link.dstVenID = Regex.Split(arr[deviceNameEnd + 10], @":")[1];
                        link.dstDevID = Regex.Split(arr[deviceNameEnd + 11], @":")[1];
                        link.dstRev = Regex.Split(arr[deviceNameEnd + 12], @":")[1];
                        for (int i = deviceNameEnd + 13; i < arr.Length; i++)
                        {
                            link.dstDeviceName += arr[i] + " ";
                            link.dstDeviceName = Regex.Replace(link.dstDeviceName, @"{", "");
                            if (arr[i].Contains("}"))
                            {
                                link.dstDeviceName = Regex.Replace(link.dstDeviceName, @"}", "");
                                deviceNameEnd = i;
                                break;
                            }
                        }
                        link.dstLid = Int32.Parse(Methods.Hex2decString(Regex.Split(arr[deviceNameEnd + 1], @":")[1]));
                        link.dstPortNum = Int32.Parse(Methods.Hex2decString(Regex.Split(arr[deviceNameEnd + 2], @":")[1]));
                        //
                        subnetInfo.Add(link);
                        subnetInfoTable.Rows.Add(link.srcDeviceName,
                            link.srcPortNum,
                            link.dstDeviceName,
                            link.dstPortNum);
                    }//try
                    catch { }
                }// while
            }//try
            catch { }
            sr.Dispose();
        }
        //
        //----------------------------------------------------
        //
        public Object[] getSubnetInfo()
        {
            Object[] res = new object[2];
            res[0] = subnetInfoTable;
            res[1] = subnetInfo;
            //
            return res;
        }
        //
        //----------------------------------------------------
        //

        public void Dispose()
        {
            if (subnetInfoTable != null)
            {
                subnetInfoTable.Dispose();
            }
        }
    }
}
